-module(synchro).
-export([start/2, get_time/1]).
-import(werkzeug, [to_String/1]).

start(DataSink, InitialDelta) ->
	PID = self(),
	spawn(fun() -> reminder(PID) end),
	synchronize(DataSink, InitialDelta).

%% Dem Hauptprozess bescheidsagen, dass er der Ausgabe melden soll, was sein aktuelles Delta ist
reminder(SynchroPID) ->
	receive
		after 3000 ->
			SynchroPID ! printDelta
	end,
	reminder(SynchroPID).

synchronize(DataSink, CurrentDelta) ->
	receive
		{gettime, PID} ->
			PID ! {time, timestamp(CurrentDelta)},
			%io:format("Zeitstempel wurde abgefragt und ~w wurde zurückgeliefert~n", [timestamp(CurrentDelta)]),
			synchronize(DataSink, CurrentDelta);
		{sync, Time, ForeignTime} ->
			
			%%Ich würde mal sagen, dass der neue Zeitstempel mit 20% in das aktuelle Delta reinspielt... Dadurch würde sich die Uhr automatisch
			%%iwann beim Durchschnitt aller Uhren einpendeln.
			%0.8 * (systime + Delta) + 0.2 * ForeignTime - (systime) 
			synchronize(DataSink, round(0.95*Time+0.05*ForeignTime)-(Time-CurrentDelta));
		printDelta ->
			DataSink ! lists:concat(["Aktuelles Delta: ", to_String(CurrentDelta)]),
			synchronize(DataSink, CurrentDelta)
	end.


get_time(Synchro) ->
	Synchro ! {gettime, self()},
	receive
		{time, Timestamp} -> Timestamp
	end.

%%Wenn Nachricht eingeht, dann kann ich die Framenummer & Slotnummer aus dem Absendezeitstempel errechnen
%% Slotnummer Absendezeitstempel in (ms) / 40 ms und abgerundet.
%% Framenummer ist einfach die Anzahl der Sekunden




%% Aufgrund von Schaltsekunden etc. kann es sein, dass die Stationen auf komplett unterschiedlichen Frames senden...
%% Eigentlich ja kein Problem, wenn die Uhren ein paar Frames auseinander laufen... Naja... mal sehen... wir benutzen jetzt
%% Die Unix-Time-Epoch, weil ich kp hab, wie ich aus dem UTC-Datum die Sekunden rausrechnen soll.
timestamp(Delta) ->
	{MSecs, Secs, MicroSecs} = now(),
	%Alternativ: 
	% {MSecs, Secs MicroSecs} = os:timestamp(),
	% (calendar:datetime_to_gregorian_seconds(calendar:now_to_universal_time({MSecs, Secs MicroSecs}))-719528*24*3600)*1000+round(MicroSecs/1000)+Delta
	((MSecs*1000000)+Secs)*1000 + round(MicroSecs/1000) + Delta.